# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
"""
Finishing Stacks
"""

from ..packlib.info import ACE, KING
from ..utillib.misc import kwdefault
from .. import pilelib as stack
from .. import helpstrings as hs
from ..gamelib import state
from .. import comparecards as cmp_cards


class AceKingSS_Foundation(stack.SS_Foundation):
    """
    Build in rank by same suit. Play top.
      - E 4. Build up. Base `ACE`.
      - W 4. Init `KING`. Build down. Base `KING`.
    """

    def __init__(self, x, y, game, **cap):
        """
        __init__(x, y, game) -> None

        :Parameters:
          x : int
            left x-coordinate.

          y : int
            top y-coordinate.

          game : pysollib.game.Game
            current Game.

        seealso::
          `pysollib.stackcaps` with details of *capability* keywords.
        """
        nsuits = len(game['suits'])
        npile = len(game.s['foundations'])
        basecaps = ({'base_rank': KING, 'dir': -1} if (npile / nsuits) % 2
                     else {'base_rank': ACE, 'dir': 1})
        kwdefault(cap, **basecaps)
        super(AceKingSS_Foundation, self).__init__(x, y, game, **cap)


class RanksSS_Foundation(stack.AbstractFoundation):

    def _sequence(self, cards):
        """
        _sequence(cards) -> bool

        :Parameters:
          cards : ..pilelib.card.Card
            current card seq playing to pile.

        :return: whether card sequence matches acccording to *capabilities*.
        """
        ranks = self.game['ranks']
        return cmp_cards.isSequenceWithRANKS(cards, ranks, **self.cap)


class Amazons_Foundation(stack.FromRowStackBuildMethod, RanksSS_Foundation):

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack, cards) -> bool

        Check parent method and cards are from neighbor `game.s.rows` except
        last which maybe from any `game.s.rows`.

        :Parameters:
          from_stack : pysollib.stack.Stack
            pile from which cards playing.

          cards : ..pilelib.card.Card
            current card seq playing to pile.

        :return: pile can build with cards from played from_stack?

        seealso::
          `pysollib.stackcaps.builds` for the *capability* check.
        """
        if not super(Amazons_Foundation, self).cardsBuild(from_stack,
                                                                cards):
            return False
        s = self.game.s
        return any([len(self.cards) == self.cap['max_cards'] - 1,
                    s['foundations'].index(self) == s['rows'].index(from_stack)])


class Formic_Foundation(stack.Vary_RK_Foundation):

    def _sequence(self, cards):
        """
        _sequence(cards) -> bool

        :Parameters:
          cards : ..pilelib.card.Card
            current card seq playing to pile.

        :return: whether card sequence matches acccording to *capabilities*.
        """
        return cmp_cards.isEitherRankSequence(cards, **self.cap)

    @property
    def _helpString(self):
        """
        _helpString -> str

        :return: helpful string about pile for its canvas label.
        :rtype:  base_string
        """
        return hs.EITHER_RK_STR


class Interregnum_Foundation(stack.RK_Foundation):

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack, cards) -> bool

        Check parent method and cards are from `game.s.rows` except last which
        must be from neighbor `game.s.reserves`.

        :Parameters:
          from_stack : pysollib.stack.Stack
            pile from which cards playing.

          cards : ..pilelib.card.Card
            current card seq playing to pile.

        :return: pile can build with cards from played from_stack?

        seealso::
          `pysollib.stackcaps.builds` for the *capability* check.
        """
        if not super(Interregnum_Foundation, self).cardsBuild(from_stack,
                                                                cards):
            return False
        s = self.game.s
        if len(self.cards) == self.cap['max_cards'] - 1:
            return all([from_stack in s.reserves,
                   s['foundations'].index(self) == s['reserves'].index(from_stack)])
        else:
            return from_stack in s['rows']


class Strategy_Foundation(stack.EmptyTalonBuildMethod, stack.SS_Foundation):
    pass


class Rittenhouse_Foundation(stack.FromRowStackBuildMethod,
                                   stack.RK_Foundation):

    def __init__(self, x, y, game, **cap):
        """
        __init__(x, y, game) -> None

        :Parameters:
          x : int
            left x-coordinate.

          y : int
            top y-coordinate.

          game : pysollib.game.Game
            current Game.

        seealso::
          `pysollib.stackcaps` with details of *capability* keywords.
        """
        nsuits = len(game['suits'])
        npile = len(self.game.s['foundations'])
        assert game['decks'] == 2
        basecaps = ({'base_rank': KING, 'dir': -1} if (npile / nsuits) % 2
                     else {'base_rank': ACE, 'dir': 1})
        kwdefault(cap, **basecaps)
        super(Rittenhouse_Foundation, self).__init__(x, y, game, **cap)

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack:obj, cards:tup) -> bool

        Check parent can build with cards from from_stack of _row_ below,
        except center _row_.

        :param object from_stack: pile playing cards.
        :param tuple cards: cards playing on pile.
        :return: pile can build with cards from played from_stack?
        :rtype: boolean

        seealso:
          Method pysollib.stackcaps.builds for the *capability* check.
        """
        if not super(Rittenhouse_Foundation, self).cardsBuild(from_stack,
                                                              cards):
            return False
        ri = self.game.s['rows'].index(from_stack)
        fi = self.game.s['foundations'].index(self)
        ri -= int(ri > 4)
        return ri == 4 or ri == fi


class SlyFox_Foundation(AceKingSS_Foundation):

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack:obj, cards:tup) -> bool

        Check if pile can build with cards from from_stack. Addition either
        talon must not have cards or Game.num_dealled is less or equal 0 when
        from stack is a rowstack.

        :param object from_stack: pile playing cards.
        :param tuple cards: cards playing on pile.
        :return: pile can build with cards from played from_stack?
        :rtype: boolean

        seealso:
          Method pysollib.stackcaps.builds for the *capability* check.
        """
        if not super(SlyFox_Foundation, self).cardsBuild(from_stack, cards):
            return False
        s = self.game.s
        if from_stack in s['rows']:
            return not s['talon'].cards or not self.status == 0
        return True